//=============================================================================
/**
 * @file	comm_command_safari.c
 * @brief	データを送るためのコマンドをテーブル化しています      サファリ用です
 *          comm_command_safari.h の enum と同じ並びである必要があります
 * @author	ohno@gamefreak.co.jp
 * @date    2009.04.18
 */
//=============================================================================

#include "common.h"
#include "communication/communication.h"
#include "comm_command_safari.h"
#include "savedata/safari_sv.h"
#include "field_event.h"  //FieldEvent_GetSpecialWork
#include "fieldsys.h"  //FIELDSYS_WORK


//==============================================================================
//  プロトタイプ宣言
//==============================================================================
typedef struct _EV_SAFARICOMM_WORK EV_SAFARICOMM_WORK;

typedef void (*PTRSafariStateFunc)(EV_SAFARICOMM_WORK* pWork);

struct _EV_SAFARICOMM_WORK{
    PTRSafariStateFunc pState;
    SAFARI_SAVE* pSafari;
    SAFARI_LAYOUT recvBuffer[SAFARI_LAYOUT_MAX];
} ;


enum {
    _SAFARI_STNO = 12,
    _SAFARI_ENDNO
};


//==============================================================================
//  static定義
//==============================================================================

static int _getSafariSize(void );
static void _commandRecvSafariData(int netID, int size, void* pData, void* pWork);
static u8* _getSafariBuffer(int netID, void* pWork, int size);


//==============================================================================
//	テーブル宣言
//  comm_command_battle.h の enum と同じならびにしてください
//  CALLBACKを呼ばれたくない場合はNULLを書いてください
//  コマンドのサイズを返す関数を書いてもらえると通信が軽くなります
//  _getZeroはサイズなしを返します。_getVariableは可変データ使用時に使います
//  comm_command_field.cを参考にしてみてください
//==============================================================================
static const CommPacketTbl _CommPacketTbl[] = {
	{_commandRecvSafariData,		_getSafariSize,		_getSafariBuffer},	// COMM_SAFARI_DATA
};


// ステートの初期化

static void _changeStateDebug(PTRSafariStateFunc state, EV_SAFARICOMM_WORK* pWork, int line);
static void _changeState(PTRSafariStateFunc state, EV_SAFARICOMM_WORK* pWork);

#ifdef PM_DEBUG
#if DEBUG_ONLY_FOR_ohno
#define   _CHANGE_STATE(state,pWork)  _changeStateDebug(state,pWork,__LINE__)
#else
#define   _CHANGE_STATE(state,pWork)  _changeState(state,pWork )
#endif
#else  //PM_DEBUG
#define   _CHANGE_STATE(state,pWork)  _changeState(state,pWork )
#endif //PM_DEBUG


//--------------------------------------------------------------
/**
 * @brief    通信管理ステートの変更
 * @param   state  変えるステートの関数
 * @param   time   ステート保持時間
 * @retval  none
 */
//--------------------------------------------------------------

static void _changeState(PTRSafariStateFunc state, EV_SAFARICOMM_WORK* pWork)
{
    pWork->pState = state;
}

//--------------------------------------------------------------
/**
 * @brief    通信管理ステートの変更
 * @param   state  変えるステートの関数
 * @param   time   ステート保持時間
 * @retval  none
 */
//--------------------------------------------------------------
#ifdef PM_DEBUG
static void _changeStateDebug(PTRSafariStateFunc state, EV_SAFARICOMM_WORK* pWork, int line)
{
    OHNO_PRINT("sf_state: %d\n",line);
    _changeState(state, pWork);
}
#endif


//--------------------------------------------------------------
/**
 * @brief   サファリ通信初期化
 * @param   pWork   セーブデータポインタ
 * @retval  none
 */
//--------------------------------------------------------------

static void CommCommandSafariInitialize(EV_SAFARICOMM_WORK *pWork)
{
    CommCommandInitialize(_CommPacketTbl, NELEMS(_CommPacketTbl), pWork);

}
//------------------------------------------------------------------------------
/**
 * @brief    サファリのレイアウト構造体サイズ
 * @param   none
 * @retval  none
 */
//------------------------------------------------------------------------------

static int _getSafariSize(void )
{
	return sizeof(SAFARI_LAYOUT);
}


static u8* _getSafariBuffer(int netID, void* pWork, int size)
{
    EV_SAFARICOMM_WORK* pSafari = pWork;
    GF_ASSERT(netID < SAFARI_LAYOUT_MAX);
    return (u8*)&pSafari->recvBuffer[netID];
}


//------------------------------------------------------------------------------
/**
 * @brief   サファリSAFARI_LAYOUTデータコールバック
 * @param   none
 * @retval  none
 */
//------------------------------------------------------------------------------

static void _commandRecvSafariData(int netID, int size, void* pData, void* pWork)
{
    EV_SAFARICOMM_WORK* pSafari = pWork;

    if(CommGetCurrentID() != netID){
        SafariSv_SetLayout(pSafari->pSafari,SAFARI_LAYOUT_FRIEND,(SAFARI_LAYOUT*)pData);
		SafariSv_SetFriendStatus(pSafari->pSafari, CommInfoGetMyStatus(netID), HEAPID_WORLD);
    }
}

//--------------------------------------------------------------
/**
 * @brief   サファリ通信初期化
 * @param   pWork   セーブデータポインタ
 * @retval  none
 */
//--------------------------------------------------------------

static EV_SAFARICOMM_WORK* _createWork(void)
{
    EV_SAFARICOMM_WORK* pWork = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(EV_SAFARICOMM_WORK));
    MI_CpuClear8(pWork, sizeof(EV_SAFARICOMM_WORK));
    return pWork;
}

//--------------------------------------------------------------
/**
 * @brief   サファリ通信初期化
 * @param   pWork   セーブデータポインタ
 * @retval  none
 */
//--------------------------------------------------------------

static BOOL GMEVENT_SafariMatchState(GMEVENT_CONTROL * event)
{
    EV_SAFARICOMM_WORK *pWork = FieldEvent_GetSpecialWork(event);

    if(!pWork->pState){
        sys_FreeMemoryEz(pWork);
        return TRUE;
    }
    pWork->pState(pWork);
    return FALSE;
}

//------------------------------------------------------------------------------
/**
 * @brief   終わりのタイミングを図る
 * @param   none
 * @retval  none
 */
//------------------------------------------------------------------------------

static void _safariEndTime(EV_SAFARICOMM_WORK* pWork)
{
    if(CommIsTimingSync(_SAFARI_ENDNO)){
        MYSTATUS* pMy = CommInfoGetMyStatus(1-CommGetCurrentID());
        _CHANGE_STATE(NULL,pWork);
    }
}

//------------------------------------------------------------------------------
/**
 * @brief   終わりのタイミングを図る
 * @param   none
 * @retval  none
 */
//------------------------------------------------------------------------------

static void _safariTimingStart(EV_SAFARICOMM_WORK* pWork)
{
    if(CommIsTimingSync(_SAFARI_STNO)){
        if(CommInfoGetMyStatus(1)){
            CommSendFixHugeSizeData(COMM_SAFARI_COMMAND_DATA,
                                SafariSv_GetLayoutPointer(pWork->pSafari,SAFARI_LAYOUT_MINE));
            CommTimingSyncStart(_SAFARI_ENDNO);

            _CHANGE_STATE(_safariEndTime,pWork);
        }
    }


}

//------------------------------------------------------------------------------
/**
 * @brief   プロセス起動
 * @param   none
 * @retval  none
 */
//------------------------------------------------------------------------------

void EventCmd_SafariTransData(FIELDSYS_WORK * fsys)
{
	EV_SAFARICOMM_WORK *pWork = _createWork();

    pWork->pSafari = SaveData_GetSafariSave(fsys->savedata);
    CommCommandSafariInitialize(pWork);
    CommTimingSyncStart(_SAFARI_STNO);
    _CHANGE_STATE(_safariTimingStart,pWork);
    FieldEvent_Call(fsys->event, GMEVENT_SafariMatchState, pWork);
}

